home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
121_01
/
sh.c
< prev
next >
Wrap
Text File
|
1985-08-19
|
15KB
|
714 lines
/*
HEADER: CUG 121.??;
TITLE: sh - a 'little shell' command interpreter;
VERSION: 2.2;
DATE: 01/06/86;
DESCRIPTION: "The little shell is designed to provide a `Unix-like'
shell for CP/M, replacing the CP/M CCP as the primary user
interface. It provides two convenient mechanisms for
chaining commands together: they may be typed on a single
line, separated by commas; or files of commands called Shell
scripts may be executed.
The CP/M operating environment does not lend itself to the
use of frequently invoked commands in the form of executable
files. Consequently, the shell has an extensive array of
built-in commands, including: cat, ccp, cd, clr, echo, exit,
lock, logout, ls, pwd, ren, rm, sleep, unlock.
The above is accomplished at a cost: the shell is written in
BDS C and is five times the size of the CP/M CCP; hence it
takes somewhat longer to load into memory at warm boots.
Also, since the shell clobbers the CCP, submit does not work
when the shell is invoked.";
KEYWORDS: shell, command, interpreter;
SYSTEM: CP/M;
FILENAME: SH.C;
WARNINGS: "Copyright (c) 1982 Steve Blasingame.
Requires doglob.h and fcb.h for compile.";
AUTHORS: Steve Blasingame;
COMPILERS: BDS-C 1.50;
*/
#include <bdscio.h>
#include <hardware.h>
#include "fcb.h"
#include "doglob.h"
#define EOT 4 /* ascii eot */
#define PROMPT "$ " /* prompt string */
#define TABSIZE 7 /* spaces in a tab */
#define CNTLH 8 /* backspace */
#define DEL 0x7f /* ascii del */
#define QUIT 0x1c /* cntl-backslash */
#define LINEKILL 24 /* cntl-x */
#define SLEEPNO 16 /* sleep constant for 4 Mz Z80a */
#define COMMENT '#' /* comment line */
#define stdin 0 /* for console io */
#define stdout 1 /* for console io */
#define FILE struct _buf
#define SHBUF 0xf54b /* Buffer in current bios */
char combuf[MAXLINE]; /* command line buffer */
char globs[GLOBMAX*FILENAMESIZE]; /* expansion buffer */
int argvp[20]; /* array of argument pointers */
int argcp; /* argument count for execv */
int testmode; /* verbose flag */
int flag; /* for lst function */
/* Structure of Shell's Storage Area in the CBIOS */
struct exbuf {
char _shdsk; /* current directory */
int _shsav; /* buffer save flag */
char _nocli; /* no shell option */
char _shbuf[BUFSIZ]; /* buffer */
};
struct exbuf *iop; /* pointer to bios buffer */
int parse(); /* parse command line */
int dolocal(); /* do built-in shell commands */
int lexecv(); /* local execv until C1.45a */
char *b_gets(); /* local crt driver */
char pwd(); /* return current logical disk */
char chdir(); /* select disk */
int filprt(); /* list selected file on screen */
int lst(); /* format directory listing */
int dofile(); /* process shell script */
int flock(); /* lock or unlock file */
int doshell(); /* exec the shell */
int expand(); /* expand global filenames */
int dozap(); /* interactively delete files */
int doglob(); /* parse global file expressions */
int more(); /* list multiple files on screen */
int crfil(); /* fill memory */
int strcmp();
main(argc,argv)
int argc;
char *argv[];
{
char *cp;
_allocp = 0; /* initializer */
iop = SHBUF; /* initializer */
testmode = 0; /* initializer */
iop->_nocli = 0; /* default shell on reboot */
if (argc == 2 && (strcmp(argv[1],"-T") == 0)) testmode =1;
if (argc == 3 && (strcmp(argv[1],"-F") == 0)) parse(strlower(argv[2]));
bdos(0x0e, iop->_shdsk); /* restore cwd */
while (1) {
crfil(combuf,MAXLINE,0);
if (!iop->_shsav) {
puts(PROMPT);
if (!b_gets(combuf))
break;
else {
cp = combuf;
if (parse(cp) == -1)
puts("what?\n");
}
}
else {
strcpy(combuf,&iop->_shbuf);
iop->_shsav = 0;
cp = combuf;
if (parse(cp) == -1)
puts("syntax error\n");
}
}
chdir('a'); /* home directory */
if (execl("a:login",0) == -1) /* admittedly a kluge */
;
doshell();
}
parse(cp)
char *cp;
{
int i;
char *pointer;
i=0;
argvp[i]=cp;
if (testmode) puts(cp);
if (*cp == '\n')
return 0;
else {
while(*cp == ' ') /* skip blanks */
cp++;
argvp[i]=cp;
while(*++cp != NULL) {
if (*cp == ' ') {
i++;
*cp = NULL;
argvp[i]=cp+1;
}
else if (*cp == ';') {
if (cp == combuf || *(cp+1) != ' ')
return -1;
else {
i++;
*cp = NULL;
argvp[i]=NULL;
cp += 2;
strcpy(iop->_shbuf,cp);
iop->_shsav = 1;
break;
}
}
else if (*cp == '\n') {
i++;
*cp = NULL;
argvp[i]=NULL;
break;
}
}
argcp = 0;
while(1) {
if (!argvp[argcp]) break;
argcp++;
}
if (dolocal(&argvp)) {
return 0;
}
else {
pointer = &argvp + 1;
if (lexecv(argvp[0], pointer) == -1) {
if (dofile(argcp,&argvp) == -1) {
puts(argvp[0]);
puts(": not found\n");
}
return 0;
}
}
}
return(-1);
}
dolocal(ptr)
char *ptr[];
{
int value;
char *tpoint;
if (strcmp(*ptr,"clr") == 0) {
puts(CLEARS);
return 1;
}
else if (strcmp(*ptr,"ccp") == 0) {
iop->_nocli = 1; /* set no shell mode */
bios(1,0); /* warm boot cpm */
}
else if (strcmp(*ptr,"exit") == 0) {
iop->_shsav = 0; /* flush shell buffer */
bios(1,0); /* warm boot cpm */
}
else if (**ptr == COMMENT) return 1;
else if (strcmp(*ptr,"logout") == 0) {
chdir('a'); /* set default directory */
execl("a:login",0);
;
return 1;
}
else if (strcmp(*ptr,"echo") == 0) {
++ptr;
while (*ptr != 0) {
puts(*ptr);
putchar(' ');
ptr++;
}
putchar('\n');
return 1;
}
else if (strcmp(*ptr,"pwd") == 0) {
putchar(pwd()); /* print current disk */
puts(":\n");
return 1;
}
else if (strcmp(*ptr,"cd") == 0) {
chdir(**++ptr); /* set default disk */
return 1;
}
else if (strcmp(*ptr,"sleep") == 0) {
value = (SLEEPNO * atoi(*++ptr));
sleep(value);
return 1;
}
else if (strcmp(*ptr,"rm") == 0) {
++ptr; /* remove files */
if (*ptr == 0 || **ptr == '\n' || **ptr == 0) {
puts("usage: rm [file] [file...]\n");
return 1;
}
while (*ptr != NULL && **ptr != NULL) {
expand(dozap,*ptr,0);
ptr++;
}
return 1;
}
else if (strcmp(*ptr,"lock") == 0) {
++ptr;
if (*ptr == 0 || **ptr == '\n' || **ptr == 0) {
puts("usage: lock [file] [file...]\n");
return 1;
}
while (*ptr != NULL && **ptr != NULL) {
expand(flock,*ptr,1);
ptr++;
}
return 1;
}
else if (strcmp(*ptr,"unlock") == 0) {
++ptr;
if (*ptr == 0 || **ptr == '\n' || **ptr == 0) {
puts("usage: unlock [file] [file...]\n");
return 1;
}
while (*ptr != NULL && **ptr != NULL) {
expand(flock,*ptr,0);
ptr++;
}
return 1;
}
else if (strcmp(*ptr,"mv") == 0) {
tpoint = *++ptr;
++ptr;
value = *ptr;
if (tpoint == 0 || *tpoint == '\n' || **ptr == '\n' || *ptr == 0) {
puts("usage: mv [source] [dest]\n");
return 1;
}
if (index(tpoint,"*") != -1 || index(tpoint,"?") != -1) {
puts(tpoint);
puts(": ambiguous\n");
return 1;
}
else if (index(value,"*") != -1 || index(value,"?") != -1) {
puts(value);
puts(": ambiguous\n");
return 1;
}
else if (fstat(*ptr) == -1) {
if ((value=fstat(tpoint)) == 1) {
puts(tpoint);
puts(": readonly\n");
return 1;
}
else if (value == 0) {
if (rename(tpoint,*ptr) == -1) {
puts(*ptr);
puts(": file not found\n");
return 1;
}
}
else if (value == -1) {
puts(tpoint);
puts(": file not found\n");
return 1;
}
}
else {
puts(*ptr);
puts(": file already exists\n");
return 1;
}
return 1;
}
else if (strcmp(*ptr,"ls") == 0) {
++ptr;
flag = 0; /* a kluge */
if (!(*ptr == 0 || **ptr == '\n' || **ptr == 0)) {
while (*ptr != NULL && **ptr != NULL) {
expand(lst,*ptr,0);
ptr++;
}
putchar('\n');
}
else {
expand(lst,"*.*",0);
putchar('\n');
}
return 1;
}
else if (strcmp(*ptr,"cat") == 0) {
++ptr;
if (*ptr == 0 || **ptr